package dev.ece.core.cells.model.base;

import org.lwjgl.opengl.GL11;

import dev.ece.core.cells.model.AbstractUI;
import dev.ece.core.vertex.VAO;
import dev.ece.core.vertex.VBO;
import dev.ece.util.lib.IntRectangle;
import dev.ece.util.lib.Rectangle;
import dev.ece.util.lib.Vector2f;
import dev.ece.util.lib.Vector3f;
import dev.ece.util.tools.Camera;

public abstract class SquareOfNineUI<T> extends AbstractUI<T> {
	
	public static final int DEFAULT_CENTER_DISTANCE = 1;
	
	private Vector3f[] vertice;
	
	private Vector2f[] uv;
	
	private VBO verticeVBO;
	
	private VBO uvVBO;
	
	private VAO vao;
	
	private float width;
	
	private float height;
	
	/**
	 * 纹理偏移量
	 */
	private Rectangle textureClipping;
	
	/**
	 * 中间区域距离边界的距离：类似于padding
	 */
	private IntRectangle centerClipping;
	
	public SquareOfNineUI(float width, float height) {
		this(new Rectangle(0, 0, 1, 1), width, height, new IntRectangle(DEFAULT_CENTER_DISTANCE, DEFAULT_CENTER_DISTANCE, DEFAULT_CENTER_DISTANCE, DEFAULT_CENTER_DISTANCE));
	}
	
	public SquareOfNineUI(float width, float height, IntRectangle centerClipping) {
		this(new Rectangle(0, 0, 1, 1), width, height, centerClipping);
	}
	
	public SquareOfNineUI(Rectangle textureClipping, float width, float height) {
		this(textureClipping, width, height, new IntRectangle(DEFAULT_CENTER_DISTANCE, DEFAULT_CENTER_DISTANCE, DEFAULT_CENTER_DISTANCE, DEFAULT_CENTER_DISTANCE));
	}
	
	/**
	 * 
	 * @param textureClipping
	 * @param width
	 * @param height
	 * @param centerClipping 上下左右切割纹理,中间部分拉伸
	 */
	public SquareOfNineUI(Rectangle textureClipping, float width, float height, IntRectangle centerClipping) {
		if(textureClipping ==  null) {
			throw new IllegalArgumentException("参数textureClipping不能为null.");
		}
		if(centerClipping == null) {
			throw new IllegalArgumentException("参数centerClipping不能为null.");
		}
		this.width = width;
		this.height = height;
		this.textureClipping = textureClipping;
		this.centerClipping = centerClipping;
		this.init();
		this.setup();
	}
	
	protected void init() {
		final Vector2f textureSize = this.createTextureSize();
		final float hw = this.getWidth() / 2;
		final float hh = this.getHeight() / 2;
		final float tleft = this.textureClipping.left;
		final float ttop = this.textureClipping.top;
		final float tright = this.textureClipping.right;
		final float tbottom = this.textureClipping.bottom;
		final float left = this.centerClipping.left / textureSize.getX();
		final float top = this.centerClipping.top / textureSize.getY();
		final float right = this.centerClipping.right / textureSize.getX();
		final float bottom = this.centerClipping.bottom / textureSize.getY();
		vertice = new Vector3f[54];
		uv = new Vector2f[54];
		//左上角
		vertice[0] = new Vector3f(-hw, hh, 0);
		vertice[1] = new Vector3f(-hw, hh - centerClipping.top, 0);
		vertice[2] = new Vector3f(-hw + centerClipping.left, hh, 0);
		
		vertice[3] = vertice[2];
		vertice[4] = vertice[1];
		vertice[5] = new Vector3f(-hw + centerClipping.left, hh - centerClipping.top, 0);
		uv[0] = new Vector2f(tleft, ttop);
		uv[1] = new Vector2f(tleft, ttop + top);
		uv[2] = new Vector2f(tleft + left, ttop);
		
		uv[3] = uv[2];
		uv[4] = uv[1];
		uv[5] = new Vector2f(tleft + left, ttop + top);
		
		//右上角
		vertice[6] = new Vector3f(hw - centerClipping.right, hh, 0);
		vertice[7] = new Vector3f(hw - centerClipping.right, hh - centerClipping.top, 0);
		vertice[8] = new Vector3f(hw, hh, 0);
		
		vertice[9] = vertice[8]; 
		vertice[10] = vertice[7]; 
		vertice[11] = new Vector3f(hw, hh - centerClipping.top, 0);
		
		uv[6] = new Vector2f(tright - right, ttop);
		uv[7] = new Vector2f(tright - right, ttop + top);
		uv[8] = new Vector2f(tright, ttop);
		
		uv[9] = uv[8];
		uv[10] = uv[7];
		uv[11] = new Vector2f(tright, ttop + top);
		//左下角
		vertice[12] = new Vector3f(-hw, -hh + centerClipping.bottom, 0);
		vertice[13] = new Vector3f(-hw, -hh, 0);
		vertice[14] = new Vector3f(-hw + centerClipping.left, -hh + centerClipping.bottom, 0);
		
		vertice[15] = vertice[14];
		vertice[16] = vertice[13];
		vertice[17] = new Vector3f(-hw + centerClipping.left, -hh, 0);
		
		uv[12] = new Vector2f(tleft, tbottom - bottom);
		uv[13] = new Vector2f(tleft, tbottom);
		uv[14] = new Vector2f(tleft + left, tbottom - bottom);
		
		uv[15] = uv[14];
		uv[16] = uv[13];
		uv[17] = new Vector2f(tleft + left, tbottom);
		//右下角
		vertice[18] = new Vector3f(hw - centerClipping.right, -hh + centerClipping.bottom, 0);
		vertice[19] = new Vector3f(hw - centerClipping.right, -hh, 0);
		vertice[20] = new Vector3f(hw, -hh + centerClipping.bottom, 0);
		
		vertice[21] = vertice[20];
		vertice[22] = vertice[19];
		vertice[23] = new Vector3f(hw, -hh, 0);
		
		uv[18] = new Vector2f(tright - right, tbottom - bottom);
		uv[19] = new Vector2f(tright - right, tbottom);
		uv[20] = new Vector2f(tright, tbottom - bottom);
		
		uv[21] = uv[20];
		uv[22] = uv[19];
		uv[23] = new Vector2f(tright, tbottom);
		//上中
		vertice[24] = vertice[2];
		vertice[25] = vertice[5];
		vertice[26] = vertice[6];
		
		vertice[27] = vertice[26];
		vertice[28] = vertice[25];
		vertice[29] = vertice[7];
		
		uv[24] = uv[2];
		uv[25] = uv[5];
		uv[26] = uv[6];
		
		uv[27] = uv[26];
		uv[28] = uv[25];
		uv[29] = uv[7];
		//左中
		vertice[30] = vertice[1];
		vertice[31] = vertice[12];
		vertice[32] = vertice[5];
		
		vertice[33] = vertice[32];
		vertice[34] = vertice[31];
		vertice[35] = vertice[14];
		
		uv[30] = uv[1];
		uv[31] = uv[12];
		uv[32] = uv[5];
		
		uv[33] = uv[32];
		uv[34] = uv[31];
		uv[35] = uv[14];
		//右中
		vertice[36] = vertice[7];
		vertice[37] = vertice[18];
		vertice[38] = vertice[11];
		
		vertice[39] = vertice[38];
		vertice[40] = vertice[37];
		vertice[41] = vertice[20];
		
		uv[36] = uv[7];
		uv[37] = uv[18];
		uv[38] = uv[11];
		
		uv[39] = uv[38];
		uv[40] = uv[37];
		uv[41] = uv[20];
		//下中
		vertice[42] = vertice[14];
		vertice[43] = vertice[17];
		vertice[44] = vertice[18];
		
		vertice[45] = vertice[44];
		vertice[46] = vertice[43];
		vertice[47] = vertice[19];
		
		uv[42] = uv[14];
		uv[43] = uv[17];
		uv[44] = uv[18];
		
		uv[45] = uv[44];
		uv[46] = uv[43];
		uv[47] = uv[19];
		//中间
		vertice[48] = vertice[5];
		vertice[49] = vertice[14];
		vertice[50] = vertice[7];
		
		vertice[51] = vertice[50];
		vertice[52] = vertice[49];
		vertice[53] = vertice[18];
		
		uv[48] = uv[5];
		uv[49] = uv[14];
		uv[50] = uv[7];
		
		uv[51] = uv[50];
		uv[52] = uv[49];
		uv[53] = uv[18];
	}
	
	protected void setup() {
		verticeVBO = VBO.newInstance(vertice);
		uvVBO = VBO.newInstance(uv);
		VBO.unbind();
	}
	
	@Override
	public void onInitialize() {
		vao = new VAO();
		vao.bind();
		vao.bindVertexArrayBuffer(verticeVBO, 3);
		vao.bindVertexArrayBuffer(uvVBO, 2);
		vao.finish();
		verticeVBO = null;
		uvVBO = null;
	}
	
	protected abstract Vector2f createTextureSize();
	
	@Override
	public void onRender(Camera camera, T value) {
		vao.bind();
		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, vertice.length);
	}

	public Rectangle getTextureClipping() {
		return textureClipping;
	}

	public IntRectangle getCenterClipping() {
		return centerClipping;
	}

	@Override
	public float getWidth() {
		return this.width;
	}

	@Override
	public float getHeight() {
		return this.height;
	}

	@Override
	public void destroy() {
		if(vao != null) {
			vao.destroy();
		}
		vao = null;
		vertice = null;
		uv = null;
	}
}
